﻿using System;
using System.Collections.Generic;
using System.Linq;
using ReactiveGraph.Core;

namespace ReactiveGraph.Uat.ResolvableValueUat
{
    public class PropertyQueue<T> : Property<T>
    {
        private readonly Func<QueueValue<T>, object> _keySelector;
        private QueueValue<T> _manualValue;
        private readonly List<QueueValue<T>> _secondaryValues = new List<QueueValue<T>>();

        public PropertyQueue(string name, Func<QueueValue<T>,object> keySelector ) 
            : base(name)
        {
            _keySelector = keySelector;
        }

        public T ManualValue
        {
            get
            {
                return _manualValue == null ?
                                                default(T) : _manualValue.Value;
            }
            set
            {
                CatchTopLevelValueChange(() =>
                                             {
                                                 _manualValue = new QueueValue<T>("Manual",value);
                                             });
            }
        }

        private void CatchTopLevelValueChange(Action action)
        {
            var previous = GetTopLevelValue();
            action();
            var newValue = GetTopLevelValue();
            if(!Equals(newValue , previous))
                OnPropertyChanged(newValue);

        }

        public override T Value
        {
            get
            {
                return GetTopLevelValue();
            }
            set
            {
                ManualValue = value;
            }
        }

        private T GetTopLevelValue()
        {
            if(_manualValue != null) return ManualValue;
            if (!_secondaryValues.Any()) return default(T);
            return _secondaryValues
                .OrderBy(_keySelector)
                .Select(q => q.Value)
                .FirstOrDefault();
        }

        public void SetSecondaryValue(string name, T value)
        {
            CatchTopLevelValueChange(() => _secondaryValues.Add(new QueueValue<T>(name, value)));
        }

        public void ClearSecondaryValue(string name)
        {
            CatchTopLevelValueChange(() => _secondaryValues.RemoveAll(value => value.Name.Equals(name)));
            ;
        }
    }
}